﻿using GuardMonitor.Model;
using GuardMonitor.Utils;
using Newtonsoft.Json.Linq;
using SmartWeighMonitor;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using 新门禁.Utils;                 // 你的封装（HikLprSession/HikLprUtils）
using WF = System.Windows.Forms;     // WinForms 别名，给 PictureBox 用
using 门禁系统.ViewModel;
using static 新门禁.Utils.HikLprSession;
using System.Drawing.Printing;

namespace 新门禁
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        MainViewModel mainViewModel;
        MainWindow mainWindow;
        private DispatcherTimer timer;
        HttpServer server;


        SynchronizationContext _syncContext = null;

        delegate void MyDelegate(Object value);
        private VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK m_PlateResultCB = null;
        private VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK m_PlateResultCB2 = null;
        private VzClientSDK.VZLPRC_GPIO_RECV_CALLBACK m_gpio_recvCB = null;

        System.Windows.Forms.PictureBox m_pictureBoxHik;
        private string m_sAppPath;

        // —— 海康会话 & 播放控件 —— //
        public  static HikLprSession _camIn;
        public static HikLprSession _camOut;
        private System.Windows.Forms.PictureBox _pbIn;
        private System.Windows.Forms.PictureBox _pbOut;

        // 简单去重（3秒）
        private string _lastInPlate = "";
        private DateTime _lastInAt = DateTime.MinValue;
        private string _lastOutPlate = "";
        private DateTime _lastOutAt = DateTime.MinValue;
      

        public MainWindow()
        {
            InitializeComponent();
            _syncContext = SynchronizationContext.Current;
            m_sAppPath = System.IO.Directory.GetCurrentDirectory();
            mainViewModel = new MainViewModel();
            this.DataContext = mainViewModel;

            mainWindow = this;
            this.Loaded += Window_Loaded;

            int seconds = App.GetBaseInfo().RefreshSeconds;
            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(seconds);
            timer.Tick += new EventHandler(timeCycle);
            timer.Start();

            // ★ 新增：窗口关闭时释放海康会话
            this.Closed += (s, e) =>
            {
                try { _camIn?.Stop(); } catch { }
                try { _camOut?.Stop(); } catch { }
            };
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            version.Text = "门禁系统 ver.1.0.1";
            VzClientSDK.VzLPRClient_Setup();
            m_gpio_recvCB = new VzClientSDK.VZLPRC_GPIO_RECV_CALLBACK(OnGPIORecv);

            server = App.GetHttpServer();
            if (null != server)
            {
                HttpServer.sendMsgEvent += Server_sendMsgEvent;
            }

            // —— 海康摄像头：保留你原逻辑，仅补充 Start —— //

            // 1) 准备两个 WinForms 播放控件（必须先挂到 Host 再 Start）
            _pbIn = new WF.PictureBox { Dock = WF.DockStyle.Fill };
            _pbOut = new WF.PictureBox { Dock = WF.DockStyle.Fill };
            hostIn.Child = _pbIn;
            hostOut.Child = _pbOut;

            // 2) 从配置读取两路参数（只配一路也可以）
            string ipIn = App.GetBaseInfo().HikVideo_URL;        // 或 HikVideo_URL1
            ushort portIn = TryPort(App.GetBaseInfo().HikVideo_Port);
            string userIn = App.GetBaseInfo().HikVideo_Username;
            string pwdIn = App.GetBaseInfo().HikVideo_Password;
            int chIn = 1;

            string ipOut = App.GetBaseInfo().HikVideo_URL2;      // 第二路可为空
            ushort portOut = TryPort(App.GetBaseInfo().HikVideo_Port2);
            string userOut = App.GetBaseInfo().HikVideo_Username2;
            string pwdOut = App.GetBaseInfo().HikVideo_Password2;
            int chOut = 1;

            // 3) 创建会话（名称用于区分方向）
            // 入口相机（判断配置是否完整）
            _camIn = (!string.IsNullOrWhiteSpace(ipIn) && portIn != 0 && !string.IsNullOrWhiteSpace(userIn))
                     ? HikLprUtils.Create("入口", ipIn, portIn, userIn, pwdIn, chIn)
                     : null;


            _camOut = (!string.IsNullOrWhiteSpace(ipOut) && portOut != 0 && !string.IsNullOrWhiteSpace(userOut))
                      ? HikLprUtils.Create("出口", ipOut, portOut, userOut, pwdOut, chOut)
                      : null;

            // 4) 订阅车牌事件
            if (_camIn != null)
                _camIn.PlateDetected += (plate, camName) => OnPlateIn(plate, camName);

            if (_camOut != null)
                _camOut.PlateDetected += (plate, camName) => OnPlateOut(plate, camName);

            // 5) ★ 新增：启动会话（登录 + 布防 + 预览）
            try
            {
                _camIn.Start(_pbIn.Handle);
            }
            catch (Exception ex)
            {
                MessageBox.Show("入口启动失败：" + ex.Message);
            }

            if (_camOut != null)
            {
                try
                {
                    _camOut.Start(_pbOut.Handle);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("出口启动失败：" + ex.Message);
                }
            }

            LoadData();
        }



        // —— 海康入口回调 —— //
        private void OnPlateIn(string plate, string camName)
        {
            // 去重（3秒内相同车牌忽略）
            if (plate == _lastInPlate && (DateTime.Now - _lastInAt).TotalSeconds < 3) return;
            _lastInPlate = plate; _lastInAt = DateTime.Now;

            // 展示
            Dispatcher.BeginInvoke(new Action(() =>
            {
                txtInCarNo.Text = plate;
                //txtInResult.Text = "识别成功";
            }));

            // HTTP 上报（direction=in）
            _ = PostPlateAsyncIN(plate, "in", camName);
        }

        // —— 海康出口回调 —— //
        private void OnPlateOut(string plate, string camName)
        {
            if (plate == _lastOutPlate && (DateTime.Now - _lastOutAt).TotalSeconds < 3) return;
            _lastOutPlate = plate; _lastOutAt = DateTime.Now;

            Dispatcher.BeginInvoke(new Action(() =>
            {
                txtOutCarNo.Text = plate;
                txtOutResult.Text = "识别成功";
            }));

            // HTTP 上报（direction=out）
            _ = PostPlateAsyncOut(plate, "out", camName);
        }

        // —— 统一的 HTTP 上报（沿用你项目里的 HttpPostHelper） —— //
        /*private Task PostPlateAsync(string plate, string type, string cameraName)
        {
            return Task.Run(delegate
            {
                try
                {
                    String gateCode = App.GetBaseInfo().gateCode;
                    string ip = App.GetBaseInfo().HttpServerIp;
                    string port = App.GetBaseInfo().HttpServerPort;
                    // 2) 请求体（按后端字段改名）
                    JObject body = new JObject();
                    body.Add("carNo", plate);
                    body.Add("type", type);
                    body.Add("gateCode", gateCode);

                    // 3) 发送
                    String result = HttpPostHelper.doHttpPost("http://" + ip + ":" + port + "/qd-s-factory/access/carApproachs", body.ToString());//改变车辆进场状态
                    JObject resJSON = JObject.Parse(result);
                    string status = (string)resJSON.GetValue("code");
                    string message = (string)resJSON.GetValue("message");
                    if ("00000".Equals(status))
                    {
                        JObject checkResultObj = new JObject();
                        if (type.Equals("in"))
                        {
                            txtInResult.Foreground = Brushes.Green;
                            txtInResult.Text = "正常放行";
                            TcpRequestUtil.Main(type);//抬杆
                            LoadData();
                        }
                        else if (type.Equals("out"))
                        {

                            txtOutResult.Foreground = Brushes.Green;
                            txtOutResult.Text = "正常放行";
                            TcpRequestUtil.Main(type);//抬杆
                            LoadData();
                        }
                    }
                    else
                    {
                        if ("in".Equals(type))
                        {
                            txtInResult.Foreground = Brushes.Red;

                            txtInResult.Text = message;
                            LoadData();


                        }
                        else if ("out".Equals(type))
                        {
                            txtOutResult.Foreground = Brushes.Red;
                            txtOutResult.Text = message;
                            LoadData();

                        }
                    }
                }
                catch (Exception ex)
                {
             
                }
            });
        }*/


        /// <summary>
        /// 出厂逻辑
        /// </summary>
        /// <param name="plate"></param>
        /// <param name="type"></param>
        /// <param name="cameraName"></param>
        /// <returns></returns>
        private Task PostPlateAsyncOut(string plate, string type, string cameraName)
        {
            return Task.Run(delegate
            {
                try
                {
                
                    string ip = App.GetBaseInfo().HttpServerIp;
                    string port = App.GetBaseInfo().HttpServerPort;
                    var param = new Dictionary<string, string>();

                    param["useStatus"] = "0";
                    param["payStatus"] = "1";
                    param["carNumber"] = plate;  // plate 变量
                    // 3) 发送
                    String result = HttpPostHelper.doHttpGet("http://" + ip + ":" + port + "/qd-s-consumerapp/wxPaymentLog/detailOne", param);//改变车辆进场状态
                    JObject resJSON = JObject.Parse(result);
                    string status = (string)resJSON.GetValue("code");
                    string message = (string)resJSON.GetValue("message");
                    if ("00000".Equals(status))
                    {
                         JToken data = resJSON.GetValue("data");
                        if (data != null && data.Type == JTokenType.Object && data.HasValues )
                        {
                          
                            // UI 必须回到主线程操作
                            Dispatcher.Invoke(() =>
                            {
                                txtOutResult.Foreground = Brushes.Green;
                                txtOutResult.Text = "正常放行";
                            });

                            _camOut?.BarrierGateCtrl(BarrierCmd.Open, channel: 1, laneNo: 1, entranceNo: 1);//抬杆
                            String parkCode = App.GetBaseInfo().parkCode;
                            JObject body2 = new JObject();
                            body2.Add("plateNo", plate);
                            body2.Add("direct", "1");
                            body2.Add("parkCode", parkCode);
                            // 3) 发送
                            String result2 = HttpPostHelper.doHttpPost("http://" + ip + ":" + port + "/qd-s-factory/kafka/pushCar", body2.ToString());

                            LoadData();
                        }
                        else
                        {
                            // UI 必须回到主线程操作
                            Dispatcher.Invoke(() =>
                            {
                                txtOutResult.Foreground = Brushes.Red;
                                txtOutResult.Text = "未缴费";
                            });
                           

                        }
                
                    }
                    else
                    {
                      
                            txtInResult.Foreground = Brushes.Red;

                            txtInResult.Text = message;
                            LoadData();
                      
                    }
                }
                catch (Exception ex)
                {

                }
            });
        }

        /// <summary>
        /// 进厂识别车牌后逻辑
        /// </summary>
        /// <param name="plate"></param>
        /// <param name="type"></param>
        /// <param name="cameraName"></param>
        /// <returns></returns>
        private Task PostPlateAsyncIN(string plate, string type, string cameraName)
        {
            return Task.Run(delegate
            {
                try
                {

                    _camIn?.BarrierGateCtrl(BarrierCmd.Open, channel: 1, laneNo: 1, entranceNo: 1);//进厂抬杆
                                                                                                   // UI 必须回到主线程操作
                    Dispatcher.Invoke(() =>
                    {
                        txtInResult.Foreground = Brushes.Green;
                        txtInResult.Text = "正常放行";
                    });

                    String parkCode = App.GetBaseInfo().parkCode;
                    string ip = App.GetBaseInfo().HttpServerIp;
                    string port = App.GetBaseInfo().HttpServerPort;
                    // 2) 请求体（按后端字段改名）
                    JObject body = new JObject();
                    body.Add("plateNo", plate);
                    body.Add("direct", "0");
                    body.Add("parkCode", parkCode);
                    // 3) 发送
                    String result = HttpPostHelper.doHttpPost("http://" + ip + ":" + port + "/qd-s-factory/kafka/pushCar", body.ToString());              
                }
                catch (Exception ex)
                {

                }
            });
        }

        private void OnGPIORecv(int handle, int nGPIOId, int nVal, IntPtr pUserData)
        {
            int value = nVal;
        }

      

        private void LoadData()
        {
            new Task(() =>
            {
                getAccessList();  //这里也一样，继续往上找
            }).Start();
        }

       

        private async void getAccessList()
        {
            try
            {

                String ip = App.GetBaseInfo().HttpServerIp;
                String port = App.GetBaseInfo().HttpServerPort;
                String parkCode = App.GetBaseInfo().parkCode;
                String pageSizeString = App.GetBaseInfo().pageSize;
                int pageSize = int.Parse(pageSizeString);
               JObject newJson= new JObject();
                newJson.Add("areaCode", parkCode);
                newJson.Add("pageSize", pageSize);

                 var result = HttpPostHelper.doHttpPost("http://" + ip + ":" + port + "/qd-s-factory/ftyFactoryCar/listCar", newJson.ToString());
                Console.Write(result);
                // var result = HttpPostHelper.doHttpGet("http://" + ip + ":" + port + "/qd-s-factory/ftyFactoryCar/list", param);
                String msg =  result;
                JObject respJson = JObject.Parse(msg);
                String status = respJson["success"].ToString();
                if ("true".Equals(status.ToLower()))
                {
                    _syncContext.Post(SetDataLists, respJson);
                }
            }
            catch (Exception ex)
            {
                LogObject.WriteLog(ex.ToString(), "Message");
            }
        }

        private void SetDataLists(object obj)
        {
            string flag = App.GetBaseInfo().ButtonLimit;
            try
            {
                JObject jsonObj = obj as JObject;
                bool success = (bool)jsonObj.GetValue("success");
                if (!success) return;
                int idx = 0;
                mainViewModel.carInList.Clear();
                JObject dataObj = (JObject)jsonObj.GetValue("data");
      /*          JArray waitInArray = (JArray)dataObj.GetValue("willInList");

                idx = 0;
                foreach (JObject item in waitInArray)
                {
                    idx++;
                    Record record = getRecordByJSON(item);
                    record.xh = idx.ToString();
                    if (flag.Equals("1"))
                    {
                        record.Visibility = "Visible";
                    }
                    else
                    {
                        record.Visibility = "Hidden";
                    }

                    if (flag.Equals("1"))
                    {
                        record.checkVisibility = "Visible";
                    }
                    else
                    {
                        record.checkVisibility = "Hidden";
                    }
                    mainViewModel.carInList.Add(record);
                }*/

                mainViewModel.carInList2.Clear();
                idx = 0;
                JArray hasInArray = (JArray)dataObj.GetValue("inList");
                foreach (JObject item in hasInArray)
                {
                    idx++;
                    Record record = getRecordByJSON(item);
                    record.xh = idx.ToString();
                    mainViewModel.carInList2.Add(record);
                }
/*
                mainViewModel.carOutList.Clear();
                idx = 0;
                JArray waitOutArray = (JArray)dataObj.GetValue("willOutList");
                foreach (JObject item in waitOutArray)
                {
                    idx++;
                    Record record = getRecordByJSON(item);
                    record.xh = idx.ToString();
                    if (flag.Equals("1"))
                    {
                        record.Visibility = "Visible";
                    }
                    else
                    {
                        record.Visibility = "Hidden";
                    }
                    mainViewModel.carOutList.Add(record);
                }*/

                mainViewModel.carOutList2.Clear();
                idx = 0;
                JArray hasOutArray = (JArray)dataObj.GetValue("outList");
                foreach (JObject item in hasOutArray)
                {
                    idx++;
                    Record record = getRecordByJSON(item);
                    record.xh = idx.ToString();
                    mainViewModel.carOutList2.Add(record);
                }
            }
            catch (Exception ex)
            {
                LogObject.WriteLog("send message: ", "loadData");
            }
        }

        public Record getRecordByJSON(JObject item)
        {
            Record record = new Record();
            record.id = (String)item.GetValue("id");
            record.xh = (String)item.GetValue("xh");
            record.carNo = (String)item.GetValue("carNumber");
            record.invName = (String)item.GetValue("invName");
            record.orderNo = (String)item.GetValue("orderNo");
            record.cTime = (String)item.GetValue("createTime");

/*            String status = (String)item.GetValue("checkStatus");
            if (status.Equals("0"))
            {
                record.CheckStatus = "待安检";
            }
            else if (status.Equals("1"))
            {
                record.CheckStatus = "安检通过";
            }
            else
            {
                record.CheckStatus = "安检未通过";
            }*/
            return record;
        }

        void dealLoadData(Object obj)
        {
            string buttonLimit = App.GetBaseInfo().ButtonLimit;
            mainViewModel.LoadData((string)obj, buttonLimit);
        }

        private void DGInList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
        }

        private void Server_sendMsgEvent(object msg)
        {
            MyDelegate dele = new MyDelegate(DealMessage);
            this.Dispatcher.Invoke(dele, msg);
        }

        void DealMessage(object obj)
        {
            JObject jsonObj = JObject.Parse(obj.ToString());
            String type = (String)jsonObj.GetValue("type");
            if ("GetCarNo".Equals(type))
            {
                JObject jsonDetail = (JObject)jsonObj.GetValue("detail");
                String inOut = (String)jsonDetail.GetValue("inOut");
                String carNo = (String)jsonDetail.GetValue("carNo");
                if ("in".Equals(inOut))
                {
                    txtInCarNo.Text = carNo;
                    txtInResult.Text = "";
                }
                else if ("out".Equals(inOut))
                {
                    txtOutCarNo.Text = carNo;
                    txtOutResult.Text = "";
                }
            }
            else if ("Check".Equals(type))
            {
                bool result = (bool)jsonObj.GetValue("result");
                String inOut = (String)jsonObj.GetValue("inOut");
                String message = (String)jsonObj.GetValue("message");

                if (result)
                {
                    if ("in".Equals(inOut))
                    {
                        txtInResult.Foreground = Brushes.Green;
                        txtInResult.Text = "正常放行";
                    }
                    else if ("out".Equals(inOut))
                    {
                        txtOutResult.Foreground = Brushes.Green;
                        txtOutResult.Text = "正常放行";
                    }
                    LoadData();
                }
                else
                {
                    if ("in".Equals(inOut))
                    {
                        txtInResult.Foreground = Brushes.Red;
                        txtInResult.Text = message;
                    }
                    else if ("out".Equals(inOut))
                    {
                        txtOutResult.Foreground = Brushes.Red;
                        txtOutResult.Text = message;
                    }
                }
            }
        }

        private void timeCycle(object sender, EventArgs e)
        {
            LoadData();
        }

        public void doDataRefresh(object sender, RoutedEventArgs e)
        {
            LoadData();
        }

        private void showPassWindowIn(object sender, RoutedEventArgs e)
        {
            Record record = (Record)DGInList.SelectedItem;

            PassWindow passWindow = new PassWindow();
            passWindow.setInOutType("in");
            passWindow.setCarNo(record.carNo);
            passWindow.Owner = mainWindow;

            bool result = (bool)passWindow.ShowDialog();
            if (result)
            {
                txtInCarNo.Text = record.carNo;
                txtInResult.Foreground = Brushes.Green;
                txtInResult.Text = "手动放行";
                LoadData();
            }
        }

        private void showPassWindowOut(object sender, RoutedEventArgs e)
        {
            Record record = (Record)DGOutList.SelectedItem;

            PassWindow passWindow = new PassWindow();
            passWindow.setInOutType("out");
            passWindow.setCarNo(record.carNo);
            passWindow.Owner = mainWindow;

            bool result = (bool)passWindow.ShowDialog();
            if (result)
            {
                txtOutCarNo.Text = record.carNo;
                txtOutResult.Foreground = Brushes.Green;
                txtOutResult.Text = "手动放行";
                LoadData();
            }
        }

        private void showCheckWindowIn(object sender, RoutedEventArgs e)
        {
            Record record = (Record)DGInList.SelectedItem;
            CheckWindow checkWindow = new CheckWindow(); 
            checkWindow.setBillNo(record.id);
            checkWindow.Owner = mainWindow;
            bool result = (bool)checkWindow.ShowDialog();
            if (result)
            {
                LoadData();
            }
        }

        private void DGOutList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
        }

        private static ushort TryPort(string s)
        {
            ushort v;
            return ushort.TryParse(s, out v) ? v : (ushort)0;
        }

        private void ruchangtest(object sender, RoutedEventArgs e)
        {
            /*            string ipOut = App.GetBaseInfo().InAlarmOutPutPortNumber;
                        int result = Convert.ToInt32(ipOut); 

                        _camIn?.PulseAlarmOut(result);*/

            _camOut?.BarrierGateCtrl(BarrierCmd.Open, channel: 1, laneNo: 1, entranceNo: 1);
           // _camOut?.BarrierGateCtrl(BarrierCmd.Open, channel: 1, laneNo: 1, entranceNo: 1);

            // MessageBox.Show(_camIn.ToString());
        }

        private void chuchangtest(object sender, RoutedEventArgs e)//落杆
        {
            /*  string ipOut = App.GetBaseInfo().OutAlarmOutPutPortNumber;
              int result = Convert.ToInt32(ipOut);
              _camOut?.PulseAlarmOut(result);*/

            _camOut?.BarrierGateCtrl(BarrierCmd.Close, channel: 1, laneNo: 1, entranceNo: 1);
        }

        private void sdfxIN(object sender, RoutedEventArgs e)
        {

            HandPassWindow handpassWindow = new HandPassWindow();
            handpassWindow.setInOutType("in");
            //handpassWindow.setCarNo(record.carNo);
            handpassWindow.Owner = mainWindow;

            bool result = (bool)handpassWindow.ShowDialog();
            if (result)
            {
                txtInCarNo.Text = handpassWindow.getCarNo();
                //txtInCarNo.Text = handpassWindow.carNo;
                txtInResult.Foreground = Brushes.Green;
                txtInResult.Text = "手动放行";
                LoadData();
            }

        }

        private void sdfxOUT(object sender, RoutedEventArgs e)
        {
            HandPassWindow handpassWindow = new HandPassWindow();
            handpassWindow.setInOutType("out");
            //handpassWindow.setCarNo(record.carNo);
            handpassWindow.Owner = mainWindow;

            bool result = (bool)handpassWindow.ShowDialog();
            if (result)
            {
                txtOutCarNo.Text = handpassWindow.getCarNo();
                txtOutResult.Foreground = Brushes.Green;
                txtOutResult.Text = "手动放行";
                LoadData();
            }


            else
            {
                txtOutCarNo.Text = handpassWindow.getCarNo();
                txtOutCarNo.Foreground = Brushes.Red;
                txtOutResult.Foreground = Brushes.Red;
                txtOutResult.Text = "未缴费";
                LoadData();
            }
                
               
              
            
        }
    }
}
